/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __ILIGHT_H__
#define __ILIGHT_H__

#pragma once

#include "geom/Vector.h"
#include "sg/SceneNode.h"
#include "model/BoundingSphere.h"

enum DLL_EXPORT LightType {
	LIGHT_DIRECTIONAL = 0,
	LIGHT_POINT,
	LIGHT_SPOT
};

/** 
 * The structure passed to the shader
 */
struct sShaderLight {
	math::Vector4 position;
	math::Vector3 ambientColor;
	math::Vector3 diffuseColor;
	math::Vector3 specularColor;
	math::Vector3 attenuation;
	int lightType;	///< see LightType
};

/**
 * \ingroup CoreEngine
 *
 * The ILight interface.<br>
 * Stores information about lights in the scene. Lights must always be in world coordinates.<br>
 *
 * \date 03-28-2007
 *
 * \author juckel
 *
 * \todo Implement spot lights
 *
 */
class DLL_EXPORT ILight
{
public:
	/// Create a directional light and returns the pointer to it
	static ILight* createDirectionalLight(const math::Vector4 &directionToLight, float range, const math::Vector3 &color);

	/// Create a point light and returns the pointer to it
	static ILight* createPointLight(const math::Vector4 &position, const math::Vector3 &range, const math::Vector3 &color);
	static ILight* createPointLight(const math::Vector4 &position, float range, const math::Vector3 &color);

	/// Return the type
	LightType getLightType() const;

	/// Set the light to a specific type
	void setLightType(LightType type);

	/// Return the position for a point light source
	const math::Vector4& getPosition() const;

	/// Return the direction for a directional light source
	const math::Vector4& getDirection() const;

	/// Return the diffuse color
	const math::Vector3& getDiffuseColor() const;

	/// Return the ambient color
	const math::Vector3& getAmbientColor() const;

	/// Return the specular color
	const math::Vector3& getSpecularColor() const;

	/// Set the position of the light for a point light source
	void setPosition(const math::Vector4 &position);

	/// Set the direction of the light for a directional light source
	void setDirection(const math::Vector4 &direction);

	/// Set the diffuse color of the light source
	void setDiffuseColor(const math::Vector3 &color);

	/// Set the ambient color of the light source
	void setAmbientColor(const math::Vector3 &color);

	/// Set the specular color of the light source
	void setSpecularColor(const math::Vector3 &color);

	/// Return the range of the light source
	const math::Vector3& getRange() const;

	/// Setting the light range ( TODO: new: 25.5.07 by bjoern)
	void setRange(const math::Vector3 &range);

	const sShaderLight& getShaderLight() const;

	float dist;						///< The distance of the light source to an object

	virtual ~ILight(void);

	model::BoundingSphere* getBoundingSphere();
protected:
	/// Don't create ILight directly, use create methods instead
	ILight(void);

	// Sets the values to the specific variables
	//virtual void setValues() {};

	sShaderLight slight;

	float         fExponent;
	float         fCutoff;

	void updateBoundingSphere();
	model::BoundingSphere m_bbSphere;
};

/// Compare operator used for comparing the distance of two light sources. Uses the dist value
bool operator < (const ILight& l1, const ILight &l2);


#endif
